package com.squeekeek.util.japandict;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class RomaKanaConv {
	public static final byte TYPE_HIRA = (byte) 0xA4;
	public static final byte TYPE_KATA = (byte) 0xA5;
	
	private String vowels = "aeiou";
	private Map <String, Byte> jpmora = new HashMap <String, Byte>();
	
	public RomaKanaConv() {
		// Second-byte Hiragana in EUC-JP Encoding. First bytes are 0xA4
		// Initialize the basic fifty sounds
		this.jpmora.put("a", (byte) 0xA2);
		this.jpmora.put("i", (byte) 0xA4);
		this.jpmora.put("u", (byte) 0xA6);
		this.jpmora.put("e", (byte) 0xA8);
		this.jpmora.put("o", (byte) 0xAA);
		
		this.jpmora.put("ka", (byte) 0xAB);
		this.jpmora.put("ki", (byte) 0xAD);
		this.jpmora.put("ku", (byte) 0xAF);
		this.jpmora.put("ke", (byte) 0xB1);
		this.jpmora.put("ko", (byte) 0xB3);
		
		this.jpmora.put("sa", (byte) 0xB5);
		this.jpmora.put("si", (byte) 0xB7);
		this.jpmora.put("su", (byte) 0xB9);
		this.jpmora.put("se", (byte) 0xBB);
		this.jpmora.put("so", (byte) 0xBD);
		
		this.jpmora.put("shi", (byte) 0xB7);
		
		this.jpmora.put("ta", (byte) 0xBF);
		this.jpmora.put("ti", (byte) 0xC1);
		this.jpmora.put("tu", (byte) 0xC4);
		this.jpmora.put("te", (byte) 0xC6);
		this.jpmora.put("to", (byte) 0xC8);
		
		this.jpmora.put("chi", (byte) 0xC1);
		this.jpmora.put("tsu", (byte) 0xC4);
		
		this.jpmora.put("na", (byte) 0xCA);
		this.jpmora.put("ni", (byte) 0xCB);
		this.jpmora.put("nu", (byte) 0xCC);
		this.jpmora.put("ne", (byte) 0xCD);
		this.jpmora.put("no", (byte) 0xCE);
		
		this.jpmora.put("ha", (byte) 0xCF);
		this.jpmora.put("hi", (byte) 0xD2);
		this.jpmora.put("hu", (byte) 0xD5);
		this.jpmora.put("he", (byte) 0xD8);
		this.jpmora.put("ho", (byte) 0xDB);
		
		this.jpmora.put("fu", (byte) 0xD5);
		
		this.jpmora.put("ma", (byte) 0xDE);
		this.jpmora.put("mi", (byte) 0xDF);
		this.jpmora.put("mu", (byte) 0xE0);
		this.jpmora.put("me", (byte) 0xE1);
		this.jpmora.put("mo", (byte) 0xE2);
		
		this.jpmora.put("ya", (byte) 0xE4);
		this.jpmora.put("yu", (byte) 0xE6);
		this.jpmora.put("yo", (byte) 0xE8);
		
		this.jpmora.put("ra", (byte) 0xE9);
		this.jpmora.put("ri", (byte) 0xEA);
		this.jpmora.put("ru", (byte) 0xEB);
		this.jpmora.put("re", (byte) 0xEC);
		this.jpmora.put("ro", (byte) 0xED);
		
		this.jpmora.put("wa", (byte) 0xEF);
		this.jpmora.put("wo", (byte) 0xF2);
		
		this.jpmora.put("n", (byte) 0xF3);
		
		// Initialize the muddy sounds
		this.jpmora.put("ga", (byte) 0xAC);
		this.jpmora.put("gi", (byte) 0xAE);
		this.jpmora.put("gu", (byte) 0xB0);
		this.jpmora.put("ge", (byte) 0xB2);
		this.jpmora.put("go", (byte) 0xB4);
		
		this.jpmora.put("za", (byte) 0xB6);
		this.jpmora.put("ji", (byte) 0xB8);
		this.jpmora.put("dzu", (byte) 0xBA);
		this.jpmora.put("ze", (byte) 0xBC);
		this.jpmora.put("zo", (byte) 0xBE);
		
		this.jpmora.put("da", (byte) 0xC0);
		this.jpmora.put("dji", (byte) 0xC2);
		this.jpmora.put("dzu", (byte) 0xC5);
		this.jpmora.put("de", (byte) 0xC7);
		this.jpmora.put("do", (byte) 0xC9);
		
		this.jpmora.put("ba", (byte) 0xD0);
		this.jpmora.put("bi", (byte) 0xD3);
		this.jpmora.put("bu", (byte) 0xD6);
		this.jpmora.put("be", (byte) 0xD9);
		this.jpmora.put("bo", (byte) 0xDC);
		
		this.jpmora.put("pa", (byte) 0xD1);
		this.jpmora.put("pi", (byte) 0xD4);
		this.jpmora.put("pu", (byte) 0xD7);
		this.jpmora.put("pe", (byte) 0xDA);
		this.jpmora.put("po", (byte) 0xDD);
		
		this.jpmora.put("(ya", (byte) 0xE3);
		this.jpmora.put("(yu", (byte) 0xE5);
		this.jpmora.put("(yo", (byte) 0xE7);
		
		this.jpmora.put("(tsu", (byte) 0xC3);
	}
	
	public String getKana(String romaji) {
		String myres = getKana(romaji, RomaKanaConv.TYPE_HIRA);
		
		return myres;
	}
	
	public String getKana(String romaji, byte kanatype) {
		int i;
		
		byte[] kanabytestr = null;
		Byte[] kanabyteobjstr = null;
		ArrayList <Byte> kanastr = new ArrayList <Byte>();
		
		i = 0;
		
		while(i < romaji.length()) {
			String firstthree;
			
			try {
				firstthree = romaji.substring(i, i + 3);
			}
			catch (IndexOutOfBoundsException ioobee) {
				firstthree = romaji.substring(i);
			}

			if(firstthree.charAt(0) == 'n' && firstthree.length() == 1) {
				// Sort out n
				kanastr.add(kanatype);
				kanastr.add(this.jpmora.get("n"));
				
				i += 1;
			}
			else if(firstthree.charAt(0) == 'n' && firstthree.charAt(1) == '\'') {
				// Sort out n
				kanastr.add(kanatype);
				kanastr.add(this.jpmora.get("n"));
				
				i += 2;
			}
			else if(firstthree.charAt(0) == 'n' && !this.vowels.contains(firstthree.charAt(1) + "")) {
				// Sort out n
				kanastr.add(kanatype);
				kanastr.add(this.jpmora.get("n"));
				
				i += 1;
			}
			else if(this.vowels.contains(firstthree.charAt(0) + "")) {
				// Normal one-letter kana
				kanastr.add(kanatype);
				kanastr.add(this.jpmora.get(firstthree.charAt(0) + ""));
				
				i += 1;
			}
			else if(this.jpmora.get(firstthree.substring(0, 2)) != null) {
				// Normal two-letter kana
				kanastr.add(kanatype);
				kanastr.add(this.jpmora.get(firstthree.substring(0, 2)));
				
				i += 2;
			}
			else if(this.jpmora.get(firstthree) != null) {
				// Other three-letter kana
				kanastr.add(kanatype);
				kanastr.add(this.jpmora.get(firstthree));
				
				i += 3;
			}
			else {
				// One of the two cases: sokuon or youon
				if(firstthree.charAt(0) == firstthree.charAt(1)) {
					// Filter sokuon
					kanastr.add(kanatype);
					kanastr.add(this.jpmora.get("(tsu"));
					
					i += 1;
				}
				else {
					// Filter youon
					if(firstthree.substring(0, 2).equals("sh") || firstthree.substring(0,2).equals("ch")) {
						kanastr.add(kanatype);
						kanastr.add(this.jpmora.get(firstthree.substring(0,2) + "i"));
					}
					else {
						kanastr.add(kanatype);
						kanastr.add(this.jpmora.get(firstthree.charAt(0) + "i"));
					}
					
					// Determine the small y that is included
					if(firstthree.charAt(0) == 'j') {
						kanastr.add(kanatype);
						kanastr.add(this.jpmora.get("(y" + firstthree.charAt(1)));
						
						i += 2;
					}
					else {
						kanastr.add(kanatype);
						kanastr.add(this.jpmora.get("(y" + firstthree.charAt(2)));
						
						i += 3;
					}
				}
			}
		}
		
		kanabyteobjstr = new Byte[kanastr.size()];
		kanabytestr = new byte[kanastr.size()];
		kanabyteobjstr = kanastr.toArray(kanabyteobjstr);
		
		for(int r = 0; r < kanastr.size(); r++) {
			kanabytestr[r] = kanabyteobjstr[r];
		}
		
		try {
			return new String(kanabytestr, "EUC_JP");
		}
		catch (Exception e) {
			return "";
		}
	}
	
}
